<?php

namespace app\common\model;

class WeChatPaySplit
{

    private $mchId; // 商户号
    private $apiKey; // API密钥
    private $certPath; // 证书路径
    private $keyPath; // 私钥路径

    public function __construct($mchId, $apiKey, $certPath, $keyPath) {
        $this->mchId = $mchId;
        $this->apiKey = $apiKey;
        $this->certPath = $certPath;
        $this->keyPath = $keyPath;
    }

//读取商户api证书公钥
    public function getPublicKey(){
        return openssl_get_privatekey(file_get_contents(ROOT_PATH.'extend/cert/apiclient_cert.pem'));//商户平台API安全证书中下载，保存到服务器
    }
    //获取平台证书
    public function getzhengshu(){
        $url="https://api.mch.weixin.qq.com/v3/certificates";//获取地址
        $timestamp=time();//时间戳
        $nonce=$this->nonce_str();//获取一个随机字符串
        $body="";
        $mch_private_key=$this->getPublicKey();//读取商户api证书公钥
        $merchant_id='1326398901';//商户号
        $serial_no='2391149D5C0298EE06E79178D6C51D556D824413';//商户证书序列号
        $sign=$this->sign($url,'GET',$timestamp,$nonce,$body,$mch_private_key,$merchant_id,$serial_no);

        $header=[
            'Authorization:WECHATPAY2-SHA256-RSA2048 '.$sign,
            'Accept:application/json',
            'User-Agent:'.$merchant_id
        ];
        $result=$this->curl($url,'',$header,'GET');
        $result=json_decode($result,true);

        $serial_no=$result['data'][0]['serial_no'];//获取的平台证书序列号
        $encrypt_certificate=$result['data'][0]['encrypt_certificate'];
        $sign_key="gSbHVcE4vfk3qLbXREaDjB2IYMnyuYsi";  //APIv3密钥，商户平台API安全中获取

        $result=$this->decryptToString($encrypt_certificate['associated_data'],$encrypt_certificate['nonce'],$encrypt_certificate['ciphertext'],$sign_key);

        file_put_contents( ROOT_PATH.'extend/cert/cert.pem',$result);//获取的文件临时保存到服务器
        return $serial_no;//返回平台证书序列号
    }
    //解密返回的信息
    public function decryptToString($associatedData,$nonceStr,$ciphertext,$aesKey){
        $ciphertext=\base64_decode($ciphertext);
        if(function_exists('\sodium_crypto_aead_aes256gcm_is_available')&& \sodium_crypto_aead_aes256gcm_is_available()){
            return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext,$associatedData,$nonceStr,$aesKey);
        }

        if(PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())){
            $ctext=substr($ciphertext,0,-16);
            $authTag=substr($ciphertext,-16);
            return \openssl_decrypt(
                $ctext,
                'aes-256-gcm',
                $aesKey,
                \OPENSSL_RAW_DATA,
                $nonceStr,
                $authTag,
                $associatedData
            );
        }
        throw new \RuntimeException('php7.1');
    }


    protected function getPrivateKey($key)
    {
        return \openssl_get_privatekey(\file_get_contents($key));
    }

    protected function nonce_str()
    {
        static $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < 32; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }

    public function sign($url, $http_method, $timestamp, $nonce, $body, $mch_private_key, $merchant_id, $serial_no)
    {
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));

        $message = $http_method . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n";

        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);

        $schema = 'WECHATPAY2-SHA256-RSA2048 ';
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id, $nonce, $timestamp, $serial_no, $sign);

        return $token;
    }

    protected function getCurlHeader($url, $body, $method)
    {
        //$private_key = \Yii::$app->basePath.'/apiclient_key.pem';
        $private_key = ROOT_PATH.'extend/cert/apiclient_key.pem';
        $mch_id = '1326398901';
        $serial_no = '2391149D5C0298EE06E79178D6C51D556D824413';
        $timestamp = time();
        $nonce = $this->nonce_str();
        $sign = $this->sign($url, $method, $timestamp, $nonce, $body, $this->getPrivateKey($private_key), $mch_id,
            $serial_no);

        return [
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $sign,
            'Accept:application/json',
            'User-Agent:' . $mch_id,
            'Content-Type:application/json',
            'Wechatpay-Serial:' . $this->getzhengshu(),
        ];
    }

    public function curl($url,$data=[],$header,$method='POST'){
        $curl=curl_init();
        curl_setopt($curl,CURLOPT_URL,$url);
        curl_setopt($curl,CURLOPT_HTTPHEADER,$header);
        curl_setopt($curl,CURLOPT_HEADER,false);
        curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
        curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
        if($method=="POST"){
            curl_setopt($curl,CURLOPT_POST,TRUE);
            curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
        }
        $result=curl_exec($curl);
        curl_close($curl);
        return $result;
    }

    //请求分账API
    public function profitsharing($data){
        $requestData = [
            'appid'=>'wxc4c0760ac2557a60',//公众账号ID
            'sub_mchid'=>'1624428553',//二级商户号
            'transaction_id'=>$data['transaction_id'],//微信订单号
            'out_order_no'=>$data['out_order_no'],//商户分账单号
            /*'receivers'=>[
                [
                    'type'=>'MERCHANT_ID',//分账接收方类型  分账接收方类型，枚举值：MERCHANT_ID：商户PERSONAL_OPENID：个人 示例值：MERCHANT_ID
                    'receiver_account'=>$data['sub_mchid'],//分账接收方账号类型是MERCHANT_ID时，是商户号（mch_id或者sub_mch_id）类型是PERSONAL_OPENID时，是个人openid
                    'amount'=>$data['amount'],//分账金额
                    'description'=>'',//分账描述
                ]
            ],*/
            'finish'=>true,//是否分账完成
        ];
        $receivers = [];

        foreach ($data['receivers'] as $k=>$v){
            $receivers[] = [
                'type'=>'MERCHANT_ID',
                'receiver_account'=>$v['sub_mchid'],//分账接收方账号类型是MERCHANT_ID时，是商户号（mch_id或者sub_mch_id）类型是PERSONAL_OPENID时，是个人openid
                'amount'=>$v['amount'],//分账金额
                'description'=>'',
            ];
        }
        $requestData['receivers'] = $receivers;

        $url = 'https://api.mch.weixin.qq.com/v3/profitsharing/orders';

        $header = $this->getCurlHeader($url, json_encode($requestData), 'POST');

        $result = $this->curl($url, json_encode($requestData), $header, 'POST');

        return json_decode($result, true);
    }

    //查询分账结果API
    /*public function profitsharingQuery($data){
        $sub_mchid = $data['sub_mchid'];//二级商户号

        $transaction_id = $data['transaction_id'];// 微信支付订单号。

        $out_order_no = $data['out_order_no '];//商户分账单号

        $url = "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders?sub_mchid={$sub_mchid}
        &transaction_id={$sub_mchid}&out_order_no={$out_order_no}";

        $header = $this->getCurlHeader($url, json_encode($requestData), 'GET');

        $result = $this->curl($url, json_encode($requestData), $header, 'GET');

        return json_decode($result, true);
    }*/

}